import random
import time
# import os
# import numpy as np
#
# # pycryptodome老版本无int * EccPoint实现，新版（3.14.1）缺SHA256和ARC4链接库，本测试可用3.10.1版本
# # pip install pycryptodome==3.10.1
# from Crypto.Cipher import AES, ARC4
# from Crypto.Hash import MD5, SHA256
# from Crypto.PublicKey import ECC
# from Crypto.Signature import DSS
# from gmssl import sm2
# from gmssl.sm3 import sm3_hash
# from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
from gmssl import sm9  # "pip install gmssl"安装的版本无SM9，此gmssl库源码在：https://github.com/gongxian-ding/gmssl-python
# from pysmx.SM2 import Sign, Verify, Encrypt, Decrypt, kG, sm2_G
# from pysmx.SM3 import digest as SM3_pysmx
# from pysmx.SM4 import Sm4, ENCRYPT, DECRYPT
# from pysmx.ZUC import ZUC as ZUC_pysmx
#
# from hggm.SM2 import KDF, to_byte, SM2_n, _curves, SM2 as SM2_fast
# from hggm.SM3 import digest as SM3_my_fast
# from hggm.SM4 import SM4 as SM4_fast
# from hggm.ZUC import ZUC as ZUC_my_fast
from hggm.SM9 import SM9 as SM9_fast, fast_kG, _kP2, e as e_new
from hggm.SM9_test import SM9 as SM9_t
# from hggm.slow.SM2 import SM2
# from hggm.slow.SM3 import digest as SM3_my
# from hggm.slow.SM4 import SM4
# from hggm.slow.ZUC import ZUC as ZUC_my
from hggm.slow.SM9 import SM9, e, P2, N

from cProfile import Profile
prof = Profile()


def SM3_gmssl(data: bytes) -> bytes:
    return bytes.fromhex(sm3_hash([i for i in data]))


# 填充成16字节倍数bytes
def pad(s: bytes) -> bytes:
    n = 16 - (len(s) & 0xf)
    return s + bytes([n] * n)


# 将填充后的bytes还原
def unpad(s: bytes) -> bytes:
    return s[0:-s[-1]]


# Crypto - AES-128加密器
class AES_Cipher:
    def __init__(self, raw_key):
        self._key = raw_key if type(raw_key) is bytes and len(raw_key) == 16 else MD5.new(raw_key).digest()
        self._ecb = AES.new(self._key, AES.MODE_ECB)

    # AES加密（ECB模式）
    def enc(self, data):
        return self._ecb.encrypt(pad(data))

    # AES解密（ECB模式）
    def dec(self, data):
        assert len(data) & 0xf == 0
        return unpad(self._ecb.decrypt(data))

    # AES加密（CBC模式）
    def enc_cbc(self, iv, data):
        assert len(iv) == 16
        return AES.new(self._key, AES.MODE_CBC, iv).encrypt(pad(data))

    # AES解密（CBC模式）
    def dec_cbc(self, iv, data):
        assert len(iv) == 16
        assert len(data) & 0xf == 0
        return unpad(AES.new(self._key, AES.MODE_CBC, iv).decrypt(data))


# pysmx - SM4加密器
class SM4_pysmx:
    def __init__(self, raw_key):
        key = raw_key if type(raw_key) is bytes and len(raw_key) == 16 else SM3_pysmx(raw_key)[:16]
        self._enc = Sm4()
        self._enc.sm4_setkey(key, ENCRYPT)
        self._dec = Sm4()
        self._dec.sm4_setkey(key, DECRYPT)

    # SM4加密（ECB模式）
    def enc(self, data):
        return bytes(self._enc.sm4_crypt_ecb(pad(data)))

    # SM4解密（ECB模式）
    def dec(self, data):
        assert len(data) & 0xf == 0
        return unpad(bytes(self._dec.sm4_crypt_ecb(data)))

    # SM4加密（CBC模式）
    def enc_cbc(self, iv, data):
        assert len(iv) == 16
        return bytes(self._enc.sm4_crypt_cbc(iv, pad(data)))

    # SM4解密（CBC模式）
    def dec_cbc(self, iv, data):
        assert len(iv) == 16
        assert len(data) & 0xf == 0
        return unpad(bytes(self._dec.sm4_crypt_cbc(iv, data)))


# gmssl - SM4加密器
class SM4_gmssl:
    def __init__(self, raw_key):
        key = raw_key if type(raw_key) is bytes and len(raw_key) == 16 else SM3_gmssl(raw_key)[:16]
        self._enc = CryptSM4()
        self._enc.set_key(key, SM4_ENCRYPT)
        self._dec = CryptSM4()
        self._dec.set_key(key, SM4_DECRYPT)

    # SM4加密（ECB模式）
    def enc(self, data):
        return self._enc.crypt_ecb(data)

    # SM4解密（ECB模式）
    def dec(self, data):
        assert len(data) & 0xf == 0
        return self._dec.crypt_ecb(data)

    # SM4加密（CBC模式）
    def enc_cbc(self, iv, data):
        assert len(iv) == 16
        return self._enc.crypt_cbc(iv, data)

    # SM4解密（CBC模式）
    def dec_cbc(self, iv, data):
        assert len(iv) == 16
        assert len(data) & 0xf == 0
        return self._dec.crypt_cbc(iv, data)


# my - SM4加密器
class SM4_my:
    def __init__(self, raw_key):
        self.sm4 = SM4(raw_key if type(raw_key) is bytes and len(raw_key) == 16 else SM3_my(raw_key)[:16])

    # SM4加密（ECB模式）
    def enc(self, data):
        return self.sm4.ecb_enc(pad(data))

    # SM4解密（ECB模式）
    def dec(self, data):
        assert len(data) & 0xf == 0
        return unpad(self.sm4.ecb_dec(data))

    # SM4加密（CBC模式）
    def enc_cbc(self, iv, data):
        assert len(iv) == 16
        return self.sm4.cbc_enc(iv, pad(data))

    # SM4解密（CBC模式）
    def dec_cbc(self, iv, data):
        assert len(iv) == 16
        assert len(data) & 0xf == 0
        return unpad(self.sm4.cbc_dec(iv, data))


# my - SM4加密器（numba加速）
class SM4_my_fast:
    def __init__(self, raw_key):
        self.sm4 = SM4_fast(raw_key if type(raw_key) is bytes and len(raw_key) == 16 else SM3_my_fast(raw_key)[:16])

    # SM4加密（ECB模式）
    def enc(self, data):
        return self.sm4.ecb_enc(pad(data))

    # SM4解密（ECB模式）
    def dec(self, data):
        assert len(data) & 0xf == 0
        return unpad(self.sm4.ecb_dec(data))

    # SM4加密（CBC模式）
    def enc_cbc(self, iv, data):
        assert len(iv) == 16
        return self.sm4.cbc_enc(iv, pad(data))

    # SM4解密（CBC模式）
    def dec_cbc(self, iv, data):
        assert len(iv) == 16
        assert len(data) & 0xf == 0
        return unpad(self.sm4.cbc_dec(iv, data))


def sm4_prof_test():
    def prof_func():
        for i in range(1000):
            sm4_my = SM4_my(KA)
        # enc_data = sm4_my.enc(long_data)
        # dec_data = sm4_my.dec(enc_data)
        # assert dec_data == long_data
        # enc_data = sm4_my.enc_cbc(iv, long_data)
        # dec_data = sm4_my.dec_cbc(iv, enc_data)
        # assert dec_data == long_data
    long_data = os.urandom(5000000)
    KA = os.urandom(16)
    iv = os.urandom(16)
    sm4_my = SM4_my(KA)
    prof.runcall(prof_func)
    prof.print_stats(1)
    # prof.dump_stats('test.prof')


def sm4_compare_test():
    print('\n———————————————————————初始化和首次加解密测试———————————————————————')
    # 随机生成128位的密钥
    KA = os.urandom(16)
    KB = os.urandom(20)
    # 随机生成消息
    short_data = os.urandom(28)
    long_data = os.urandom(1128)

    print('密钥1长度：%dB  密钥2长度：%dB  短消息长度：%dB  长消息长度：%dB  单位：μs' % (len(KA), len(KB), len(short_data), len(long_data)))
    print('算法库名\t\t\t首次创建\t再次创建\t首次加密短消息\t再次加密短消息\t首次加密长消息\t再次加密长消息')

    # Crypto - AES-128
    time_1 = time.perf_counter()
    aes = AES_Cipher(KA)
    time_2 = time.perf_counter()
    aes = AES_Cipher(KB)
    time_3 = time.perf_counter()
    aes.enc(short_data)
    time_4 = time.perf_counter()
    aes.enc(short_data)
    time_5 = time.perf_counter()
    aes.enc(long_data)
    time_6 = time.perf_counter()
    aes.enc(long_data)
    time_7 = time.perf_counter()
    print('Crypto-AES\t\t%.1f\t%.1f\t%.1f\t\t%-5.1f\t\t%-5.1f\t\t%-5.1f' % ((time_2 - time_1) * 1000000,
                                                                          (time_3 - time_2) * 1000000,
                                                                          (time_4 - time_3) * 1000000,
                                                                          (time_5 - time_4) * 1000000,
                                                                          (time_6 - time_5) * 1000000,
                                                                          (time_7 - time_6) * 1000000))
    # pysmx - SM4
    time_1 = time.perf_counter()
    sm4_smx = SM4_pysmx(KA)
    time_2 = time.perf_counter()
    sm4_smx = SM4_pysmx(KB)
    time_3 = time.perf_counter()
    sm4_smx.enc(short_data)
    time_4 = time.perf_counter()
    sm4_smx.enc(short_data)
    time_5 = time.perf_counter()
    sm4_smx.enc(long_data)
    time_6 = time.perf_counter()
    sm4_smx.enc(long_data)
    time_7 = time.perf_counter()
    print('pysmx-SM4\t\t%.1f\t%.1f\t%.1f\t\t%.1f\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000,
                                                                   (time_3 - time_2) * 1000000,
                                                                   (time_4 - time_3) * 1000000,
                                                                   (time_5 - time_4) * 1000000,
                                                                   (time_6 - time_5) * 1000000,
                                                                   (time_7 - time_6) * 1000000))
    # gmssl - SM4
    time_1 = time.perf_counter()
    sm4_ssl = SM4_gmssl(KA)
    time_2 = time.perf_counter()
    sm4_ssl = SM4_gmssl(KB)
    time_3 = time.perf_counter()
    sm4_ssl.enc(short_data)
    time_4 = time.perf_counter()
    sm4_ssl.enc(short_data)
    time_5 = time.perf_counter()
    sm4_ssl.enc(long_data)
    time_6 = time.perf_counter()
    sm4_ssl.enc(long_data)
    time_7 = time.perf_counter()
    print('gmssl-SM4\t\t%.1f\t%.1f\t%.1f\t\t%.1f\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000,
                                                                   (time_3 - time_2) * 1000000,
                                                                   (time_4 - time_3) * 1000000,
                                                                   (time_5 - time_4) * 1000000,
                                                                   (time_6 - time_5) * 1000000,
                                                                   (time_7 - time_6) * 1000000))
    # my - SM4
    time_1 = time.perf_counter()
    sm4_my = SM4_my(KA)
    time_2 = time.perf_counter()
    sm4_my = SM4_my(KB)
    time_3 = time.perf_counter()
    sm4_my.enc(short_data)
    time_4 = time.perf_counter()
    sm4_my.enc(short_data)
    time_5 = time.perf_counter()
    sm4_my.enc(long_data)
    time_6 = time.perf_counter()
    sm4_my.enc(long_data)
    time_7 = time.perf_counter()
    print('my-SM4\t\t\t%.1f\t%.1f\t%.1f\t\t%-5.1f\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000,
                                                                    (time_3 - time_2) * 1000000,
                                                                    (time_4 - time_3) * 1000000,
                                                                    (time_5 - time_4) * 1000000,
                                                                    (time_6 - time_5) * 1000000,
                                                                    (time_7 - time_6) * 1000000))
    # my - SM4(fast)
    time_1 = time.perf_counter()
    sm4_my_fast = SM4_my_fast(KA)
    time_2 = time.perf_counter()
    sm4_my_fast = SM4_my_fast(KB)
    time_3 = time.perf_counter()
    sm4_my_fast.enc(short_data)
    time_4 = time.perf_counter()
    sm4_my_fast.enc(short_data)
    time_5 = time.perf_counter()
    sm4_my_fast.enc(long_data)
    time_6 = time.perf_counter()
    sm4_my_fast.enc(long_data)
    time_7 = time.perf_counter()
    print('my-SM4(fast)\t%.1f\t%.1f\t%.1f\t\t%-5.1f\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000,
                                                                         (time_3 - time_2) * 1000000,
                                                                         (time_4 - time_3) * 1000000,
                                                                         (time_5 - time_4) * 1000000,
                                                                         (time_6 - time_5) * 1000000,
                                                                         (time_7 - time_6) * 1000000))

    print('\n————————————————————————————加解密测试————————————————————————————')
    test_num = 50  # 测试次数
    # 随机生成消息
    short_data = [os.urandom(random.randint(16, 48)) for _ in range(test_num)]  # 短消息列表
    long_data = [os.urandom(random.randint(1000, 2000)) for _ in range(test_num)]  # 长消息列表
    enc_data = [b''] * test_num
    enc_data_pysmx = [b''] * test_num
    enc_data_gmssl = [b''] * test_num
    enc_data_my = [b''] * test_num
    enc_data_my_fast = [b''] * test_num
    dec_data1 = [b''] * test_num
    dec_data2 = [b''] * test_num

    print('短消息平均长度：%.1fB  长消息平均长度：%.1fB  测试次数：%d  单位：ms' %
          (np.mean(list(map(len, short_data))), np.mean(list(map(len, long_data))), test_num))
    print('ECB模式：\n算法库名\t\t\t加密短消息\t解密短消息\t加密长消息\t解密长消息')

    # Crypto - AES-128
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = aes.enc(short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = aes.dec(enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = aes.enc(long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = aes.dec(enc_data[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('Crypto-AES\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))

    # pysmx - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_smx.enc(short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_smx.dec(enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_pysmx[i] = sm4_smx.enc(long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_smx.dec(enc_data_pysmx[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('pysmx-SM4\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_aim1 = time_5 - time_1

    # gmssl - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_ssl.enc(short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_ssl.dec(enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_gmssl[i] = sm4_ssl.enc(long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_ssl.dec(enc_data_gmssl[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('gmssl-SM4\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_aim2 = time_5 - time_1

    # my - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_my.enc(short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_my.dec(enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_my[i] = sm4_my.enc(long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_my.dec(enc_data_my[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('my-SM4\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_my = time_5 - time_1

    # my - SM4(fast)
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_my_fast.enc(short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_my_fast.dec(enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_my_fast[i] = sm4_my_fast.enc(long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_my_fast.dec(enc_data_my_fast[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('my-SM4(fast)\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_my_fast = time_5 - time_1
    print('未加速时总耗时为gmssl的%.2f%%、pysmx的%.2f%%' % (time_my / time_aim2 * 100, time_my / time_aim1 * 100))
    print('加速以后总耗时为gmssl的%.2f%%、pysmx的%.2f%%、未加速的%.2f%%' % (time_my_fast / time_aim2 * 100,
                                                            time_my_fast / time_aim1 * 100,
                                                            time_my_fast / time_my * 100))
    assert enc_data_pysmx == enc_data_gmssl == enc_data_my == enc_data_my_fast

    print('\nCBC模式：\n算法库名\t\t\t加密短消息\t解密短消息\t加密长消息\t解密长消息')
    iv = os.urandom(16)

    # Crypto - AES-128
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = aes.enc_cbc(iv, short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = aes.dec_cbc(iv, enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = aes.enc_cbc(iv, long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = aes.dec_cbc(iv, enc_data[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('Crypto-AES\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))

    # pysmx - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_smx.enc_cbc(iv, short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_smx.dec_cbc(iv, enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_pysmx[i] = sm4_smx.enc_cbc(iv, long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_smx.dec_cbc(iv, enc_data_pysmx[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('pysmx-SM4\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_aim1 = time_5 - time_1

    # gmssl - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_ssl.enc_cbc(iv, short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_ssl.dec_cbc(iv, enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_gmssl[i] = sm4_ssl.enc_cbc(iv, long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_ssl.dec_cbc(iv, enc_data_gmssl[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('gmssl-SM4\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_aim2 = time_5 - time_1

    # my - SM4
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_my.enc_cbc(iv, short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_my.dec_cbc(iv, enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_my[i] = sm4_my.enc_cbc(iv, long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_my.dec_cbc(iv, enc_data_my[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('my-SM4\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_my = time_5 - time_1

    # my - SM4(fast)
    time_1 = time.perf_counter()
    for i in range(test_num):
        enc_data[i] = sm4_my_fast.enc_cbc(iv, short_data[i])  # 加密短消息
    time_2 = time.perf_counter()
    for i in range(test_num):
        dec_data1[i] = sm4_my_fast.dec_cbc(iv, enc_data[i])  # 解密短消息
    time_3 = time.perf_counter()
    for i in range(test_num):
        enc_data_my_fast[i] = sm4_my_fast.enc_cbc(iv, long_data[i])  # 加密长消息
    time_4 = time.perf_counter()
    for i in range(test_num):
        dec_data2[i] = sm4_my_fast.dec_cbc(iv, enc_data_my_fast[i])  # 解密长消息
    time_5 = time.perf_counter()
    assert dec_data1 == short_data
    assert dec_data2 == long_data
    print('my-SM4(fast)\t%.2f\t\t%.2f\t\t%.2f\t\t%.2f' %
          ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000, (time_4 - time_3) * 1000, (time_5 - time_4) * 1000))
    time_my_fast = time_5 - time_1
    print('未加速时总耗时为gmssl的%.2f%%、pysmx的%.2f%%' % (time_my / time_aim2 * 100, time_my / time_aim1 * 100))
    print('加速以后总耗时为gmssl的%.2f%%、pysmx的%.2f%%、未加速的%.2f%%' % (time_my_fast / time_aim2 * 100,
                                                            time_my_fast / time_aim1 * 100,
                                                            time_my_fast / time_my * 100))
    assert enc_data_pysmx == enc_data_gmssl == enc_data_my == enc_data_my_fast


def zuc_prof_test():
    def prof_func():
        zuc.enc(long_data)
    long_data = os.urandom(50000)
    key, iv = os.urandom(16), os.urandom(16)
    zuc = ZUC_my_fast(key, iv)
    prof.runcall(prof_func)
    prof.print_stats(1)
    # prof.dump_stats('test.prof')


def zuc_compare_test():
    # 随机生成128位的密钥和初始向量
    key, iv = os.urandom(16), os.urandom(16)
    test_data = os.urandom(128)
    test_num = 50  # 测试次数
    # 随机生成消息
    short_data = [os.urandom(random.randint(16, 48)) for _ in range(test_num)]  # 短消息列表
    long_data = [os.urandom(random.randint(1000, 2000)) for _ in range(test_num)]  # 长消息列表
    enc_data_arc4 = [b''] * test_num
    enc_data_pysmx = [b''] * test_num
    enc_data_my = [b''] * test_num
    enc_data_my_fast = [b''] * test_num
    enc_data_arc4_2 = [b''] * test_num
    enc_data_pysmx2 = [b''] * test_num
    enc_data_my2 = [b''] * test_num
    enc_data_my_fast2 = [b''] * test_num
    dec_data = [b''] * test_num
    dec_data2 = [b''] * test_num

    print('\n———————————————————————————————————————————流密码测试———————————————————————————————————————————')
    print('前两次加密消息长度：%dB\n后两项为连续加密——短消息平均长度：%.1fB  长消息平均长度：%.1fB  测试次数：%d' %
          (len(test_data), np.mean(list(map(len, short_data))), np.mean(list(map(len, long_data))), test_num))
    print('算法库名\t\t\t首次初始化(μs)\t再次初始化(μs)\t首次加密(μs)\t再次加密(μs)\t处理短消息(ms)\t处理长消息(ms)')

    # Crypto - ARC4
    time_1 = time.perf_counter()
    arc4 = ARC4.new(key)
    time_2 = time.perf_counter()
    arc4_2 = ARC4.new(key)
    time_3 = time.perf_counter()
    arc4.encrypt(test_data)
    time_4 = time.perf_counter()
    arc4_2.encrypt(test_data)
    time_5 = time.perf_counter()
    for i in range(test_num):
        enc_data_arc4[i] = arc4.encrypt(short_data[i])  # 加密短消息
    time_6 = time.perf_counter()
    for i in range(test_num):
        enc_data_arc4_2[i] = arc4.encrypt(long_data[i])  # 加密长消息
    time_7 = time.perf_counter()
    print('Crypto-ARC4\t\t%.2f\t\t\t%.2f\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t\t%.2f' %
          ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000, (time_4 - time_3) * 1000000,
           (time_5 - time_4) * 1000000, (time_6 - time_5) * 1000, (time_7 - time_6) * 1000))

    # pysmx - ZUC
    time_1 = time.perf_counter()
    zuc_smx = ZUC_pysmx(key, iv)
    time_2 = time.perf_counter()
    zuc_smx2 = ZUC_pysmx(key, iv)
    time_3 = time.perf_counter()
    zuc_smx.zuc_encrypt(test_data)
    time_4 = time.perf_counter()
    zuc_smx2.zuc_encrypt(test_data)
    time_5 = time.perf_counter()
    for i in range(test_num):
        enc_data_pysmx[i] = zuc_smx.zuc_encrypt(short_data[i])  # 加密短消息
    time_6 = time.perf_counter()
    for i in range(test_num):
        enc_data_pysmx2[i] = zuc_smx.zuc_encrypt(long_data[i])  # 加密长消息
    time_7 = time.perf_counter()
    print('pysmx-ZUC\t\t%.2f\t\t\t%.2f\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t\t%.2f' %
          ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000, (time_4 - time_3) * 1000000,
           (time_5 - time_4) * 1000000, (time_6 - time_5) * 1000, (time_7 - time_6) * 1000))
    time_aim = time_7 - time_5

    # my - ZUC
    time_1 = time.perf_counter()
    zuc_my = ZUC_my(key, iv)
    time_2 = time.perf_counter()
    zuc_my2 = ZUC_my(key, iv)
    time_3 = time.perf_counter()
    zuc_my.enc(test_data)
    time_4 = time.perf_counter()
    zuc_my2.enc(test_data)
    time_5 = time.perf_counter()
    for i in range(test_num):
        enc_data_my[i] = zuc_my.enc(short_data[i])  # 加密短消息
    time_6 = time.perf_counter()
    for i in range(test_num):
        enc_data_my2[i] = zuc_my.enc(long_data[i])  # 加密长消息
    time_7 = time.perf_counter()
    print('my-ZUC\t\t\t%.2f\t\t\t%.2f\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t\t%.2f' %
          ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000, (time_4 - time_3) * 1000000,
           (time_5 - time_4) * 1000000, (time_6 - time_5) * 1000, (time_7 - time_6) * 1000))
    time_my = time_7 - time_5

    # my - ZUC(fast)
    time_1 = time.perf_counter()
    zuc_my_fast = ZUC_my_fast(key, iv)
    time_2 = time.perf_counter()
    zuc_my_fast2 = ZUC_my_fast(key, iv)
    time_3 = time.perf_counter()
    zuc_my_fast.enc(test_data)
    time_4 = time.perf_counter()
    zuc_my_fast2.enc(test_data)
    time_5 = time.perf_counter()
    for i in range(test_num):
        enc_data_my_fast[i] = zuc_my_fast.enc(short_data[i])  # 加密短消息
    time_6 = time.perf_counter()
    for i in range(test_num):
        enc_data_my_fast2[i] = zuc_my_fast.enc(long_data[i])  # 加密长消息
    time_7 = time.perf_counter()
    print('my-ZUC(fast)\t%.2f\t\t\t%.2f\t\t\t%.2f\t\t%.2f\t\t%.2f\t\t\t%.2f' %
          ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000, (time_4 - time_3) * 1000000,
           (time_5 - time_4) * 1000000, (time_6 - time_5) * 1000, (time_7 - time_6) * 1000))
    time_my_fast = time_7 - time_5
    print('连续加密时，未加速时总耗时为pysmx的%.2f%%' % (time_my / time_aim * 100))
    print('加速以后总耗时为pysmx的%.2f%%、未加速的%.2f%%' % (time_my_fast / time_aim * 100, time_my_fast / time_my * 100))
    assert enc_data_pysmx == enc_data_my == list(map(list, enc_data_my_fast))  # 短消息加密生成的列表
    assert enc_data_pysmx2 == enc_data_my2 == list(map(list, enc_data_my_fast2))  # 长消息加密生成的列表

    # ARC4解密
    for i in range(test_num):  # 解密短消息
        dec_data[i] = arc4_2.decrypt(enc_data_arc4[i])
    for i in range(test_num):  # 解密长消息
        dec_data2[i] = arc4_2.decrypt(enc_data_arc4_2[i])
    assert dec_data == short_data and dec_data2 == long_data
    # ZUC解密
    for i in range(test_num):  # 解密短消息
        dec_data[i] = bytes(zuc_my2.enc(enc_data_my[i]))
        dec_data2[i] = zuc_my_fast2.dec(enc_data_my_fast[i]).astype(np.uint8).tobytes()
    assert dec_data == dec_data2 == short_data
    for i in range(test_num):  # 解密长消息（因为是流密码，从始至终加密和解密的顺序必须完全一致）
        dec_data[i] = bytes(zuc_my2.enc(enc_data_my2[i]))
        dec_data2[i] = zuc_my_fast2.dec(enc_data_my_fast2[i]).astype(np.uint8).tobytes()
    assert dec_data == dec_data2 == long_data


def sm3_prof_test():
    def prof_func():
        SM3_my(long_data)
    long_data = os.urandom(100000)
    prof.runcall(prof_func)
    prof.print_stats(1)
    # prof.dump_stats('test.prof')


def sm3_compare_test():
    print('—————————————————————首次Hash测试—————————————————————')
    # 随机生成消息
    long_data = os.urandom(128)

    print('消息长度：%dB  单位：μs' % (len(long_data)))
    print('算法库名\t\t\t首次Hash\t\t再次Hash')
    # Crypto - MD5
    time_1 = time.perf_counter()
    MD5.new(long_data).digest()
    time_2 = time.perf_counter()
    MD5.new(long_data).digest()
    time_3 = time.perf_counter()
    print('Crypto-MD5\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    # Crypto - SHA256
    time_1 = time.perf_counter()
    SHA256.new(long_data).digest()
    time_2 = time.perf_counter()
    SHA256.new(long_data).digest()
    time_3 = time.perf_counter()
    print('Crypto-SHA256\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    # gmssl - SM3
    time_1 = time.perf_counter()
    SM3_gmssl(long_data)
    time_2 = time.perf_counter()
    hash1 = SM3_gmssl(long_data)
    time_3 = time.perf_counter()
    print('gmssl-SM3\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    # pysmx - SM3
    time_1 = time.perf_counter()
    SM3_pysmx(long_data)
    time_2 = time.perf_counter()
    hash2 = SM3_pysmx(long_data)
    time_3 = time.perf_counter()
    print('pysmx-SM3\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    # my - SM3
    time_1 = time.perf_counter()
    SM3_my(long_data)
    time_2 = time.perf_counter()
    hash3 = SM3_my(long_data)
    time_3 = time.perf_counter()
    print('my-SM3\t\t\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    # my - SM3(fast)
    time_1 = time.perf_counter()
    SM3_my_fast(long_data)
    time_2 = time.perf_counter()
    hash4 = SM3_my_fast(long_data)
    time_3 = time.perf_counter()
    print('my-SM3(fast)\t%.1f\t\t%.1f' % ((time_2 - time_1) * 1000000, (time_3 - time_2) * 1000000))
    assert hash1 == hash2 == hash3 == hash4

    print('\n—————————————————————连续Hash测试—————————————————————')
    test_num = 100  # 测试次数
    # 随机生成消息
    short_data = [os.urandom(random.randint(16, 48)) for _ in range(test_num)]  # 短消息列表
    long_data = [os.urandom(random.randint(1000, 2000)) for _ in range(test_num)]  # 长消息列表
    hash_data = [b''] * test_num
    hash_data_gmssl = [b''] * test_num
    hash_data_gmssl2 = [b''] * test_num
    hash_data_pysmx = [b''] * test_num
    hash_data_pysmx2 = [b''] * test_num
    hash_data_my = [b''] * test_num
    hash_data_my2 = [b''] * test_num
    hash_data_my_fast = [b''] * test_num
    hash_data_my_fast2 = [b''] * test_num

    print('短消息平均长度：%.1fB  长消息平均长度：%.1fB  测试次数：%d  单位：ms' %
          (np.mean(list(map(len, short_data))), np.mean(list(map(len, long_data))), test_num))
    print('算法库名\t\t\t短消息Hash\t长消息Hash')

    # Crypto - MD5
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data[i] = MD5.new(short_data[i]).digest()  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data[i] = MD5.new(long_data[i]).digest()  # 长消息Hash
    time_3 = time.perf_counter()
    print('Crypto-MD5\t\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))

    # Crypto - SHA256
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data[i] = SHA256.new(short_data[i]).digest()  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data[i] = SHA256.new(long_data[i]).digest()  # 长消息Hash
    time_3 = time.perf_counter()
    print('Crypto-SHA256\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))

    # gmssl - SM3
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data_gmssl[i] = SM3_gmssl(short_data[i])  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data_gmssl2[i] = SM3_gmssl(long_data[i])  # 长消息Hash
    time_3 = time.perf_counter()
    print('gmssl-SM3\t\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))
    time_aim1 = time_3 - time_1

    # pysmx - SM3
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data_pysmx[i] = SM3_pysmx(short_data[i])  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data_pysmx2[i] = SM3_pysmx(long_data[i])  # 长消息Hash
    time_3 = time.perf_counter()
    print('pysmx-SM3\t\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))
    time_aim2 = time_3 - time_1

    # my - SM3
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data_my[i] = SM3_my(short_data[i])  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data_my2[i] = SM3_my(long_data[i])  # 长消息Hash
    time_3 = time.perf_counter()
    print('my-SM3\t\t\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))
    time_my = time_3 - time_1

    # my - SM3(fast)
    time_1 = time.perf_counter()
    for i in range(test_num):
        hash_data_my_fast[i] = SM3_my_fast(short_data[i])  # 短消息Hash
    time_2 = time.perf_counter()
    for i in range(test_num):
        hash_data_my_fast2[i] = SM3_my_fast(long_data[i])  # 长消息Hash
    time_3 = time.perf_counter()
    print('my-SM3(fast)\t%.2f\t\t%.2f' % ((time_2 - time_1) * 1000, (time_3 - time_2) * 1000))
    time_my_fast = time_3 - time_1
    print('未加速时总耗时为gmssl的%.2f%%、pysmx的%.2f%%' % (time_my / time_aim1 * 100, time_my / time_aim2 * 100))
    print('加速以后总耗时为gmssl的%.2f%%、pysmx的%.2f%%、未加速的%.2f%%' % (time_my_fast / time_aim1 * 100,
                                                            time_my_fast / time_aim2 * 100,
                                                            time_my_fast / time_my * 100))
    assert hash_data_gmssl == hash_data_pysmx == hash_data_my == hash_data_my_fast
    assert hash_data_gmssl2 == hash_data_pysmx2 == hash_data_my2 == hash_data_my_fast2


# 几种SM2库加密、签名的简单比较
def sm2_compare_test():
    IDA = 'ALICE123@YAHOO.COM'
    IDB = 'BILL456@YAHOO.COM'
    M = 'efficiency test！'
    k = 0x6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F
    K = '6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F'

    # A、B双方初始化
    my_A = SM2(ID=IDA)
    my_B = SM2(ID=IDB)
    my_fast_A = SM2_fast(ID=IDA, sk=my_A.sk, pk=my_A.pk)
    my_fast_B = SM2_fast(ID=IDB, sk=my_B.sk, pk=my_B.pk)
    gmssl_A = sm2.CryptSM2(hex(my_A.sk), to_byte(my_A.pk).hex())
    gmssl_B = sm2.CryptSM2(hex(my_B.sk), to_byte(my_B.pk).hex())
    p256_G = ECC._curves['p256'].G
    SM2_G = _curves[SM2_n].G
    ecc = ECC.generate(curve='p256')
    ecc_signer = DSS.new(ecc, 'fips-186-3')
    ecc_h = SHA256.new(M.encode())

    print('\n---------------------------点乘---------------------------')
    test_num = 50
    print('测试%d次 [1, n-1] 范围的随机数与SM2基点相乘' % test_num)
    k_list = [random.randint(1, SM2_n - 1) for _ in range(test_num)]
    res_list = [[] for _ in range(8)]
    time_1 = time.perf_counter()
    # gmssl
    for i in range(test_num):
        res_list[0].append(gmssl_B._kg(k_list[i], sm2_G))
    time_2 = time.perf_counter()
    # pysmx
    for i in range(test_num):
        res_list[1].append(kG(k_list[i], sm2_G, 64))
    time_3 = time.perf_counter()
    # 本实现算法一
    for i in range(test_num):
        res_list[2].append(my_A.Jacb_multiply(k_list[i], my_A.G, algo=1))
    time_4 = time.perf_counter()
    # 本实现算法二
    for i in range(test_num):
        res_list[3].append(my_A.Jacb_multiply(k_list[i], my_A.G, algo=2))
    time_5 = time.perf_counter()
    # 本实现算法三
    for i in range(test_num):
        res_list[4].append(my_A.Jacb_multiply(k_list[i], my_A.G, algo=3))
    time_6 = time.perf_counter()
    # 本实现加速版
    for i in range(test_num):
        res_list[5].append(k_list[i] * SM2_G)
    time_7 = time.perf_counter()
    # Crypto ECC
    for i in range(test_num):
        res_list[6].append(k_list[i] * p256_G)
    time_8 = time.perf_counter()
    # 预计算加速
    for i in range(test_num):
        res_list[7].append(my_fast_A.kG(k_list[i]))
    time_9 = time.perf_counter()
    time_relative = (time_9 - time_8)
    print('gmssl\t耗时%.2f ms\t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('pysmx\t耗时%.2f ms\t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('算法一\t耗时%.2f ms\t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    print('算法二\t耗时%.2f ms\t相对耗时%.2f' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative))
    print('算法三\t耗时%.2f ms\t相对耗时%.2f' % ((time_6 - time_5) * 1000, (time_6 - time_5) / time_relative))
    print('加速后\t耗时%.2f ms\t\t相对耗时%.2f' % ((time_7 - time_6) * 1000, (time_7 - time_6) / time_relative))
    print('ECC\t\t耗时%.2f ms\t\t相对耗时%.2f' % ((time_8 - time_7) * 1000, (time_8 - time_7) / time_relative))
    print('预计算\t耗时%.2f ms\t\t相对耗时%.2f' % ((time_9 - time_8) * 1000, (time_9 - time_8) / time_relative))
    for i in range(test_num):
        P1, P2, P3, P4, P5, P6, P8 = [res_list[j][i] for j in range(8) if j != 6]
        P1 = int(P1[:64], 16), int(P1[64:], 16)
        P2 = int(P2[:64], 16), int(P2[64:], 16)
        P6, P8 = P6.xy, P8.xy
        assert P1 == P2 == P3 == P4 == P5 == P6 == P8

    print('\n---------------------------加密---------------------------')
    print('A用B的公钥对消息M（%s）进行加密' % M)
    time_1 = time.perf_counter()
    # gmssl
    C_gmssl = gmssl_B.encrypt(M.encode())
    time_2 = time.perf_counter()
    # pysmx
    C_pysmx = Encrypt(M, to_byte(my_B.pk), 64)
    time_3 = time.perf_counter()
    # 本实现
    res, C_my = my_A.encrypt(M, my_B.pk)
    time_4 = time.perf_counter()
    # 本实现加速后
    res, C_my2 = my_fast_A.encrypt(M, my_B.pk)
    time_5 = time.perf_counter()
    time_relative = (time_5 - time_4)
    print('gmssl \t耗时%.2f ms\t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('pysmx \t耗时%.2f ms\t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('本实现\t耗时%.2f ms\t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    print('加速后\t耗时%.2f ms\t相对耗时%.2f' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative))

    print('\n---------------------------解密---------------------------')
    print('B用自己的私钥对密文进行解密')
    time_1 = time.perf_counter()
    # gmssl
    M_gmssl = gmssl_B.decrypt(C_gmssl)
    time_2 = time.perf_counter()
    # pysmx
    M_pysmx = Decrypt(C_pysmx, to_byte(my_B.sk), 64)
    time_3 = time.perf_counter()
    # 本实现
    res, M_my = my_B.decrypt(C_my)
    time_4 = time.perf_counter()
    # 本实现加速后
    res, M_my2 = my_fast_B.decrypt(C_my2)
    time_5 = time.perf_counter()
    time_relative = (time_5 - time_4)
    print('gmssl \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative, M_gmssl.decode()))
    print('pysmx \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative, M_pysmx.decode()))
    print('本实现\t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative, M_my.decode()))
    print('加速后\t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative, M_my2.decode()))

    print('\n---------------------------签名---------------------------')
    print('A用自己的私钥对消息M进行签名')
    time_1 = time.perf_counter()
    # gmssl
    sig_gmssl = gmssl_A.sign(M.encode(), K)
    time_2 = time.perf_counter()
    # pysmx
    sig_pysmx = Sign(M, to_byte(my_A.sk), K, 64)
    time_3 = time.perf_counter()
    # 本实现（pysmx和gmssl的签名函数内部未计算Z值和hash）
    sig_my = my_A.sign(M, k, dohash=False)
    time_4 = time.perf_counter()
    # 本实现加速后
    sig_my2 = my_fast_A.sign(M, k, dohash=False)
    time_5 = time.perf_counter()
    # ECDSA
    sig_ecc = ecc_signer.sign(ecc_h)
    time_6 = time.perf_counter()
    time_relative = (time_5 - time_4)
    print('gmssl \t耗时%.2f ms\t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('pysmx \t耗时%.2f ms\t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('本实现\t耗时%.2f ms\t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    print('加速后\t耗时%.2f ms\t相对耗时%.2f' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative))
    print('ECDSA\t耗时%.2f ms\t相对耗时%.2f' % ((time_6 - time_5) * 1000, (time_6 - time_5) / time_relative))

    print('\n---------------------------验证---------------------------')
    print('B用A的公钥对签名进行验证')
    time_1 = time.perf_counter()
    # gmssl
    res_gmssl = gmssl_A.verify(sig_gmssl, M.encode())
    time_2 = time.perf_counter()
    # pysmx
    res_pysmx = Verify(sig_pysmx, M, to_byte(my_A.pk), 64)
    time_3 = time.perf_counter()
    # 本实现（pysmx和gmssl的验证函数内部未计算Z值和hash）
    res_my = my_B.verify(M, sig_my, IDA, my_A.pk, dohash=False)
    time_4 = time.perf_counter()
    # 本实现加速后
    res_my2 = my_fast_B.verify(M, sig_my2, IDA, my_A.pk, dohash=False)
    time_5 = time.perf_counter()
    # ECDSA
    try:
        res_ecc = True
        ecc_signer.verify(ecc_h, sig_ecc)
    except ValueError:
        res_ecc = False
    time_6 = time.perf_counter()
    time_relative = (time_5 - time_4)
    print('gmssl \t耗时%.2f ms\t相对耗时%.2f\t结果：%s' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative, res_gmssl))
    print('pysmx \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative, res_pysmx))
    print('本实现\t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative, res_my))
    print('加速后\t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative, res_my2))
    print('ECDSA\t耗时%.2f ms\t相对耗时%.2f\t结果：%s' % ((time_6 - time_5) * 1000, (time_6 - time_5) / time_relative, res_ecc))


# 最简单的ECDH正确性测试
def test_ECDH_slow(verify=False):
    time_1 = time.perf_counter()
    sm2 = SM2(genkeypair=False)
    # A、B双方生成公、私钥
    dA, PA = sm2.gen_keypair()
    dB, PB = sm2.gen_keypair()
    # 验证ECC系统参数和公钥
    if verify:
        if not sm2.para_valid():
            print('椭圆曲线系统参数未通过验证：%s' % sm2.error)
            return
        if not sm2.pk_valid(PA):
            print('PA未通过验证：%s' % sm2.error)
            return
        if not sm2.pk_valid(PB):
            print('PB未通过验证：%s' % sm2.error)
            return

    # A将PA传给B，B将PB传给A

    # A、B双方计算密钥
    QA = sm2.Jacb_multiply(dA, PB)
    KA = KDF(to_byte(QA))
    QB = sm2.Jacb_multiply(dB, PA)
    KB = KDF(to_byte(QB))
    time_2 = time.perf_counter()
    print('ECDH密钥协商完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    assert KA == KB


# 最简单的ECDH正确性测试
def test_ECDH_fast():
    time_1 = time.perf_counter()
    sm2 = SM2_fast(genkeypair=False)
    # A、B双方生成公、私钥
    dA, PA = sm2.gen_keypair()
    dB, PB = sm2.gen_keypair()

    # A将PA传给B，B将PB传给A

    # 验证ECC系统参数和公钥，并生成SM2点对象
    PA, PB = sm2.on_curve(PA), sm2.on_curve(PB)
    # A、B双方计算密钥
    PB *= dA
    QA = PB
    # QA = dA * PB
    KA = KDF(to_byte(QA))
    PA *= dB
    QB = PA
    # QB = dB * PA
    KB = KDF(to_byte(QB))
    time_2 = time.perf_counter()
    print('ECDH密钥协商完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    assert KA == KB


# SM2密钥协商测试
def test_SM2_agreement(SM2, option=False):
    time_1 = time.perf_counter()
    # A、B双方初始化
    sm2_A = SM2(ID='a01')
    sm2_B = SM2(ID=0xB02)
    # A、B均掌握对方的公钥和ID
    PA, IDA = sm2_A.pk, sm2_A.ID
    PB, IDB = sm2_B.pk, sm2_B.ID

    # A 发起协商
    rA, RA = sm2_A.agreement_initiate()
    # A将RA发送给B

    # B 响应协商
    res, content = sm2_B.agreement_response(RA, PA, IDA, option)
    if not res:
        print('B报告协商错误：', content)
        return
    if option:
        RB, KB, SB, S2 = content
    else:
        RB, KB = content
        SB = None
    # B将RB、(选项SB)发送给A

    # A 协商确认
    res, content = sm2_A.agreement_confirm(rA, RA, RB, PB, IDB, SB, option)
    if not res:
        print('A报告协商错误：', content)
        return
    if option:
        KA, SA = content
    else:
        KA = content

    if option:
        # A将(选项SA)发送给B
        # B 协商确认
        res, content = sm2_B.agreement_confirm2(S2, SA)
        if not res:
            print('B报告协商错误：', content)
            return
    time_2 = time.perf_counter()
    print('SM2密钥协商完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    assert KA == KB


# SM2示例中的椭圆曲线系统参数
def demo_para():
    p = 0x8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3
    a = 0x787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498
    b = 0x63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A
    xG = 0x421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D
    yG = 0x0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2
    n = 0x8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7
    G = (xG, yG)
    h = 1
    return p, a, b, n, G, h


# SM2数字签名与验证测试
# SM2第2部分 A.1 A.2
# 验证通过，输出的r值(40f1ec59f793d9f49e09dcef49130d4194f79fb1eed2caa55bacdb49c4e755d1)与SM2第2部分 A.2中的结果一致
def test_signature(SM2):
    IDA = 'ALICE123@YAHOO.COM'
    M = 'message digest'
    dA = 0x128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263
    xA = 0x0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A
    yA = 0x7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857
    PA = (xA, yA)
    k = 0x6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F

    # A、B双方初始化
    sm2_A = SM2(*demo_para(), IDA, dA, PA)
    sm2_B = SM2(*demo_para())

    time_1 = time.perf_counter()
    # A对消息M进行签名
    sig = sm2_A.sign(M, k)

    # A将消息M签名(r, s)发送给B

    # B对消息M签名进行验证
    res = sm2_B.verify(M, sig, IDA, PA)
    time_2 = time.perf_counter()
    print('SM2签名、验证完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    print('结果：%s，R值：%s' % (res, sig[:sm2_A.keysize].hex()))


# SM2密钥协商测试2
# SM2第3部分 A.1 A.2
# 协商成功，输出的密钥(55b0ac62a6b927ba23703832c853ded4)与SM2第3部分 A.2中的结果一致
def test_SM2_agreement2(SM2, option=False):
    IDA = 'ALICE123@YAHOO.COM'
    IDB = 'BILL456@YAHOO.COM'
    dA = 0x6FCBA2EF9AE0AB902BC3BDE3FF915D44BA4CC78F88E2F8E7F8996D3B8CCEEDEE
    xA = 0x3099093BF3C137D8FCBBCDF4A2AE50F3B0F216C3122D79425FE03A45DBFE1655
    yA = 0x3DF79E8DAC1CF0ECBAA2F2B49D51A4B387F2EFAF482339086A27A8E05BAED98B
    PA = (xA, yA)
    dB = 0x5E35D7D3F3C54DBAC72E61819E730B019A84208CA3A35E4C2E353DFCCB2A3B53
    xB = 0x245493D446C38D8CC0F118374690E7DF633A8A4BFB3329B5ECE604B2B4F37F43
    yB = 0x53C0869F4B9E17773DE68FEC45E14904E0DEA45BF6CECF9918C85EA047C60A4C
    PB = (xB, yB)
    rA = 0x83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563
    x1 = 0x6CB5633816F4DD560B1DEC458310CBCC6856C09505324A6D23150C408F162BF0
    y1 = 0x0D6FCF62F1036C0A1B6DACCF57399223A65F7D7BF2D9637E5BBBEB857961BF1A
    RA = (x1, y1)
    rB = 0x33FE21940342161C55619C4A0C060293D543C80AF19748CE176D83477DE71C80
    x2 = 0x1799B2A2C778295300D9A2325C686129B8F2B5337B3DCF4514E8BBC19D900EE5
    y2 = 0x54C9288C82733EFDF7808AE7F27D0E732F7C73A7D9AC98B7D8740A91D0DB3CF4
    RB = (x2, y2)

    time_1 = time.perf_counter()
    # A、B双方初始化
    sm2_A = SM2(*demo_para(), IDA, dA, PA)
    sm2_B = SM2(*demo_para(), IDB, dB, PB)

    # A 发起协商
    # A生成rA, RA，将RA发送给B

    # B 响应协商
    res, content = sm2_B.agreement_response(RA, PA, IDA, option, rB, RB)
    if not res:
        print('B报告协商错误：', content)
        return
    if option:
        RB, KB, SB, S2 = content
    else:
        RB, KB = content
        SB = None
    # B将RB、(选项SB)发送给A

    # A 协商确认
    res, content = sm2_A.agreement_confirm(rA, RA, RB, PB, IDB, SB, option)
    if not res:
        print('A报告协商错误：', content)
        return
    if option:
        KA, SA = content
    else:
        KA = content

    if option:
        # A将(选项SA)发送给B
        # B 协商确认
        res, content = sm2_B.agreement_confirm2(S2, SA)
        if not res:
            print('B报告协商错误：', content)
            return
    time_2 = time.perf_counter()
    print('SM2密钥协商完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    print('KA == KB?: %s, value: %s, len: %d' % (KA == KB, KA.hex(), len(KA) << 3))


# SM2加解密测试
# SM2第4部分 A.1 A.2
# 加解密成功，解密后的16进制值(656e6372797074696f6e207374616e64617264)与SM2第4部分 A.2中的结果一致
def test_encryption(SM2):
    M = 'encryption standard'
    dB = 0x1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0
    xB = 0x435B39CCA8F3B508C1488AFC67BE491A0F7BA07E581A0E4849A5CF70628A7E0A
    yB = 0x75DDBA78F15FEECB4C7895E2C1CDF5FE01DEBB2CDBADF45399CCF77BBA076A42
    PB = (xB, yB)
    k = 0x4C62EEFD6ECFC2B95B92FD6C3D9575148AFA17425546D49018E5388D49DD7B4F

    # A、B双方初始化
    sm2_A = SM2(*demo_para())
    sm2_B = SM2(*demo_para(), '', dB, PB)

    time_1 = time.perf_counter()
    # A用B的公钥对消息M进行加密
    res, C = sm2_A.encrypt(M, PB, k)
    if not res:
        print('A报告加密错误：', C)
        return

    # A将密文C发送给B

    # B用自己的私钥对密文C进行解密
    res, M2 = sm2_B.decrypt(C)
    if not res:
        print('B报告解密错误：', M2)
        return
    time_2 = time.perf_counter()
    print('SM2加解密完毕，耗时%.2f ms' % ((time_2 - time_1) * 1000))
    print('结果：%s，解密得：%s(%s)' % (res, M2.hex(), M2.decode()))


# 验证SM2各功能的正确性
def test_SM2_func():
    print('\n---------------------------功能测试：慢速SM2---------------------------')
    test_ECDH_slow()
    test_SM2_agreement(SM2, True)
    test_signature(SM2)
    test_SM2_agreement2(SM2, True)
    test_encryption(SM2)
    print('\n---------------------------功能测试：快速SM2---------------------------')
    test_ECDH_fast()
    test_SM2_agreement(SM2_fast, True)
    # 以下使用SM2示例中的曲线参数，G坐标被视为不在曲线上？？？报错信息：ValueError: The EC point does not belong to the curve
    # test_signature(SM2_fast)
    # test_SM2_agreement2(SM2_fast, True)
    # test_encryption(SM2_fast)


def sm2_prof_test():
    def prof_func():
        for i in range(test_num):
            # kG2(k_list[i])
            sm2.kG(k_list[i])
            # res, C = sm2.encrypt(M, sm2.pk)
            # res, M2 = sm2.decrypt(C)
            # sig_my = sm2.sign(M)
            # res_my = sm2.verify(M, sig_my, '', sm2.pk)
    sm2 = SM2_fast()
    # M = to_byte(random.getrandbits(1024))
    # res, C = sm2.encrypt(M, sm2.pk)
    # sig_my = sm2.sign(M)
    test_num = 100
    k_list = [random.randint(1, SM2_n - 1) for _ in range(test_num)]
    prof.runcall(prof_func)
    prof.print_stats(1)


def sm9_prof_test():
    def prof_func():
        for i in range(test_num):
            # test_SM9_func(SM9_fast)
            a = sm9_1.e_de(sm9_1.Ppub_e)
            sm9_2.e_de(sm9_2.Ppub_e)


    test_num = 100
    kgc_1 = SM9_fast(ke=0x2E65B0762D042F51F0D23542B13ED8CFA2E9A0E7206361E013A283905E31F)
    sm9_1 = kgc_1.KGC_gen_user('IDA')
    kgc_2 = SM9_t(ke=kgc_1.ke)
    sm9_2 = kgc_2.KGC_gen_user('IDA')
    # k_list = [random.randint(1, N - 1) for _ in range(test_num)]
    prof.runcall(prof_func)
    prof.print_stats(2)


# 验证gmssl.SM9各功能的正确性
def test_SM9_func2():
    idA, idB, message = 'a', 'b', 'abc'
    master_public1, master_secret1 = sm9.setup('sign')
    master_public2, master_secret2 = sm9.setup('encrypt')
    dsA = sm9.private_key_extract('sign', master_public1, master_secret1, idA)
    deA = sm9.private_key_extract('encrypt', master_public2, master_secret2, idA)
    deB = sm9.private_key_extract('encrypt', master_public2, master_secret2, idB)
    print("-----------------test sign and verify---------------")
    signature = sm9.sign(master_public1, dsA, message)
    assert sm9.verify(master_public1, idA, message, signature)
    print("\t\t\t success")

    print("-----------------test key agreement---------------")
    xa, Ra = sm9.generate_ephemeral(master_public2, idB)
    xb, Rb = sm9.generate_ephemeral(master_public2, idA)
    # A将Ra发送给B，B将Rb发送给A
    ska = sm9.generate_session_key(idA, idB, Ra, Rb, deA, xa, master_public2, 'A', 128)
    skb = sm9.generate_session_key(idA, idB, Ra, Rb, deB, xb, master_public2, 'B', 128)
    assert ska == skb
    print("\t\t\t success")

    print("-----------------test encrypt and decrypt---------------")
    ct = sm9.kem_dem_enc(master_public2, idA, message, 32)
    pt = sm9.kem_dem_dec(master_public2, idA, deA, ct, 32)
    assert message == pt
    print("\t\t\t success")


# SM9库签名、密钥交换、加密的效率比较
def sm9_compare_test():
    IDA = 'ALICE123@YAHOO.COM'
    IDB = 'BILL456@YAHOO.COM'
    M = 'efficiency test!'

    # A、B双方初始化
    master_public1, master_secret1 = sm9.setup('sign')
    master_public2, master_secret2 = sm9.setup('encrypt')
    dsA = sm9.private_key_extract('sign', master_public1, master_secret1, IDA)
    deA = sm9.private_key_extract('encrypt', master_public2, master_secret2, IDA)
    deB = sm9.private_key_extract('encrypt', master_public2, master_secret2, IDB)
    kgc = SM9_t(ke=-1, ks=-1)
    sm9_A, sm9_B = kgc.KGC_gen_user(IDA), kgc.KGC_gen_user(IDB)
    kgc_fast = SM9_fast(ke=kgc.ke, ks=kgc.ks)
    sm9_fast_A, sm9_fast_B = kgc_fast.KGC_gen_user(IDA), kgc_fast.KGC_gen_user(IDB)
    # sm9_fast_A.add_contacts(IDB)
    # sm9_fast_B.add_contacts(IDA)
    # from gmssl.optimized_pairing import pairing
    # from gmssl.optimized_curve import multiply, G2, curve_order

    # print('\n---------------------------双线性对---------------------------')
    # pub_e = master_public2[2]
    # time_1 = time.perf_counter()
    # # gmssl
    # pt_gmssl = pairing(pub_e, deA)
    # time_2 = time.perf_counter()
    # # 本实现
    # pt_my = e(sm9_A.Ppub_e, sm9_A.de)
    # time_3 = time.perf_counter()
    # # 本实现加速版
    # pt_my_fast = sm9_fast_A.e_de(sm9_fast_A.Ppub_e)
    # time_4 = time.perf_counter()
    # time_relative = time_4 - time_3
    # print('gmssl\t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    # print('本实现\t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    # print('加速版\t耗时%.2f ms \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    # assert pt_my == pt_my_fast
    #
    # print('\n---------------------------G2点乘---------------------------')
    # test_num = 10
    # print('测试%d次 [1, N-1] 范围的随机数与P2点相乘' % test_num)
    # k_list = [random.randrange(1, curve_order) for _ in range(test_num)]
    # res_gmssl, res_my, res_my_fast = [], [], []
    # time_1 = time.perf_counter()
    # # gmssl
    # for i in range(test_num):
    #     res_gmssl.append(multiply(G2, k_list[i]))
    # time_2 = time.perf_counter()
    # # 本实现
    # for i in range(test_num):
    #     res_my.append(P2 * k_list[i])
    # time_3 = time.perf_counter()
    # # 本实现加速版
    # for i in range(test_num):
    #     res_my_fast.append(fast_kG(k_list[i], _kP2))
    # time_4 = time.perf_counter()
    # time_relative = time_4 - time_3
    # print('gmssl\t耗时%.2f ms  \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    # print('本实现\t耗时%.2f ms  \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    # print('加速版\t耗时%.2f ms  \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    # assert res_my == res_my_fast
    #
    # print('\n---------------------------高次幂---------------------------')
    # gs = master_public1[3]
    # time_1 = time.perf_counter()
    # # gmssl
    # res_gmssl = gs ** k_list[0]
    # time_2 = time.perf_counter()
    # # 本实现
    # res_my = sm9_A.gs ** k_list[0]
    # time_3 = time.perf_counter()
    # # 本实现加速版
    # res_my_fast = sm9_fast_A.gs_pow(k_list[0])
    # time_4 = time.perf_counter()
    # # 本实现加速版2
    # # res_my_fast2 = sm9_fast_A.gs_pow2(k_list[0])
    # # time_5 = time.perf_counter()
    # time_relative = time_4 - time_3
    # print('gmssl\t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    # print('本实现\t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    # print('加速版\t耗时%.2f ms  \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    # # print('加速版2\t耗时%.2f ms  \t相对耗时%.2f' % ((time_5 - time_4) * 1000, (time_5 - time_4) / time_relative))
    # assert res_my == res_my_fast

    klen = 128  # 密钥比特长度
    r = random.randrange(1, N)
    print('\n---------------------------密钥封装---------------------------')
    time_1 = time.perf_counter()
    # gmssl
    K_gmssl, C1_gmssl = sm9.kem_encap(master_public2, IDA, klen)
    time_2 = time.perf_counter()
    # 本实现
    K_my, C1_my = sm9_A.encaps(IDB, klen, r, False)
    time_3 = time.perf_counter()
    # 本实现加速版
    K_fast_my, C1_my_fast = sm9_fast_A.encaps(IDB, klen, r, False)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl\t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('本实现\t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('加速版\t耗时%.2f ms  \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))

    print('\n---------------------------解封装---------------------------')
    time_1 = time.perf_counter()
    # gmssl
    K2_gmssl = sm9.kem_decap(master_public2, IDA, deA, C1_gmssl, klen)
    time_2 = time.perf_counter()
    # 本实现
    res, K2_my = sm9_B.decaps(C1_my, klen)
    time_3 = time.perf_counter()
    # 本实现加速版
    res, K2_fast_my = sm9_fast_B.decaps(C1_my_fast, klen)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl \t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('本实现 \t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('加速版 \t耗时%.2f ms \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))
    assert K_gmssl == K2_gmssl
    assert K_my == K2_my
    assert K_fast_my == K2_fast_my

    print('\n---------------------------加密---------------------------')
    print('A用B的公钥对消息M（%s）进行加密' % M)
    time_1 = time.perf_counter()
    # gmssl
    C_gmssl = sm9.kem_dem_enc(master_public2, IDA, M, 32)
    time_2 = time.perf_counter()
    # 本实现
    C_my = sm9_A.encrypt(IDB, M, r, False)
    time_3 = time.perf_counter()
    # 本实现加速版
    C_my_fast = sm9_fast_A.encrypt(IDB, M, r, False)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl\t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('本实现\t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('加速版\t耗时%.2f ms  \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))

    print('\n---------------------------解密---------------------------')
    print('B用自己的私钥对密文进行解密')
    time_1 = time.perf_counter()
    # gmssl
    M_gmssl = sm9.kem_dem_dec(master_public2, IDA, deA, C_gmssl, 32)
    time_2 = time.perf_counter()
    # 本实现
    res, M_my = sm9_B.decrypt(C_my)
    time_3 = time.perf_counter()
    # 本实现加速版
    res, M_my_fast = sm9_fast_B.decrypt(C_my_fast)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative, M_gmssl))
    print('本实现 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative, M_my.decode()))
    print('加速版 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative, M_my_fast.decode()))

    print('\n---------------------------签名---------------------------')
    print('A用自己的私钥对消息M进行签名')
    time_1 = time.perf_counter()
    # gmssl
    sig_gmssl = sm9.sign(master_public1, dsA, M)
    time_2 = time.perf_counter()
    # 本实现
    sig_my = sm9_A.sign(M, r, False)
    time_3 = time.perf_counter()
    # 本实现加速版
    sig_my_fast = sm9_fast_A.sign(M, r, False)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl\t耗时%.2f ms \t相对耗时%.2f' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative))
    print('本实现\t耗时%.2f ms \t相对耗时%.2f' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative))
    print('加速版\t耗时%.2f ms  \t相对耗时%.2f' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative))

    print('\n---------------------------验证---------------------------')
    print('B用A的公钥对签名进行验证')
    time_1 = time.perf_counter()
    # gmssl
    res_gmssl = sm9.verify(master_public1, IDA, M, sig_gmssl)
    time_2 = time.perf_counter()
    # 本实现
    res_my = sm9_B.verify(IDA, M, sig_my)
    time_3 = time.perf_counter()
    # 本实现加速版
    res_my_fast = sm9_fast_B.verify(IDA, M, sig_my_fast)
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative, res_gmssl))
    print('本实现 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative, res_my))
    print('加速版 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative, res_my_fast))

    print('\n---------------------------密钥交换---------------------------')
    time_1 = time.perf_counter()
    # gmssl
    xa, Ra = sm9.generate_ephemeral(master_public2, IDB)
    xb, Rb = sm9.generate_ephemeral(master_public2, IDA)  # A将Ra发送给B，B将Rb发送给A
    ska = sm9.generate_session_key(IDA, IDB, Ra, Rb, deA, xa, master_public2, 'A', 128)
    skb = sm9.generate_session_key(IDA, IDB, Ra, Rb, deB, xb, master_public2, 'B', 128)
    time_2 = time.perf_counter()
    # 本实现
    rA, RA = sm9_A.agreement_initiate(IDB, r, False)  # A发起协商
    res, (RB, SKB, SB) = sm9_B.agreement_response(RA, IDA, True, r, outbytes=False)  # B响应协商
    res, (SKA, SA) = sm9_A.agreement_confirm(rA, RA, RB, IDB, SB, True)  # A协商确认
    res, content = sm9_B.agreement_confirm2(SA)  # B协商确认
    time_3 = time.perf_counter()
    # 本实现加速版
    rA, RA = sm9_fast_A.agreement_initiate(IDB, r, False)  # A发起协商
    res, (RB, SKB_fast, SB) = sm9_fast_B.agreement_response(RA, IDA, True, r, outbytes=False)  # B响应协商
    res, (SKA_fast, SA) = sm9_fast_A.agreement_confirm(rA, RA, RB, IDB, SB, True)  # A协商确认
    res, content = sm9_fast_B.agreement_confirm2(SA)  # B协商确认
    time_4 = time.perf_counter()
    time_relative = time_4 - time_3
    print('gmssl \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_2 - time_1) * 1000, (time_2 - time_1) / time_relative, ska == skb))
    print('本实现 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_3 - time_2) * 1000, (time_3 - time_2) / time_relative, SKA == SKB))
    print('加速版 \t耗时%.2f ms \t相对耗时%.2f\t结果：%s' % ((time_4 - time_3) * 1000, (time_4 - time_3) / time_relative, SKA_fast == SKB_fast))


# 验证SM9各功能的正确性
def test_SM9_func(SM9_my=SM9):
    IDA, IDB, message = 'Alice', 'Bob', 'Chinese IBS standard'
    kgc = SM9_my(ks=0x130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4,
                 ke=0x2E65B0762D042F51F0D23542B13ED8CFA2E9A0E7206361E013A283905E31F)
    sm9_A, sm9_B = kgc.KGC_gen_user(IDA), kgc.KGC_gen_user(IDB)
    if SM9_my == SM9_fast:  # 互相添加对方为常用联系人
        sm9_A.add_contacts(IDB)
        sm9_B.add_contacts(IDA)
    assert bytes(sm9_A.gs).hex().swapcase().endswith('F0F071D7D284FCFB')
    print("-----------------test sign and verify---------------")
    r = 0x033C8616B06704813203DFD00965022ED15975C662337AED648835DC4B1CBE
    signature = sm9_A.sign(message, r)
    assert signature.hex().swapcase().endswith('827CC2ACED9BAA05')
    assert sm9_B.verify(IDA, message, signature)
    print("success")

    print("-----------------test key agreement---------------")
    rA = 0x5879DD1D51E175946F23B1B41E93BA31C584AE59A426EC1046A4D03B06C8
    rA, RA = sm9_A.agreement_initiate(IDB, rA)  # A发起协商
    # A将RA发送给B
    rB = 0x018B98C44BEF9F8537FB7D071B2C928B3BC65BD3D69E1EEE213564905634FE
    res, content = sm9_B.agreement_response(RA, IDA, True, rB)  # B响应协商
    if not res:
        print('B报告协商错误：', content)
        return
    RB, SKB, SB = content
    # B将RB、SB发送给A
    res, content = sm9_A.agreement_confirm(rA, RA, RB, IDB, SB, True)  # A协商确认
    if not res:
        print('A报告协商错误：', content)
        return
    SKA, SA = content
    assert SKA.hex().swapcase() == '68B20D3077EA6E2B825315836FDBC633'
    # A将SA发送给B
    res, content = sm9_B.agreement_confirm2(SA)  # B协商确认
    if not res:
        print('B报告协商错误：', content)
        return
    assert SKA == SKB
    print("success")

    print("-----------------test encrypt and decrypt---------------")
    message = 'Chinese IBE standard'
    kgc = SM9_my(ke=0x01EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22)
    sm9_A, sm9_B = kgc.KGC_gen_user(IDA), kgc.KGC_gen_user(IDB)
    if SM9_my == SM9_fast:  # 互相添加对方为常用联系人
        sm9_A.add_contacts(IDB)
        sm9_B.add_contacts(IDA)
    C = sm9_A.encrypt(IDB, message, 0xAAC0541779C8FC45E3E2CB25C12B5D2576B2129AE8BB5EE2CBE5EC9E785C)
    assert C.hex().swapcase().endswith('378CDD5DA9513B1C')
    res, content = sm9_B.decrypt(C)
    if not res:
        print('解密错误：', content)
        return
    assert message == content.decode()
    print("success")


if __name__ == "__main__":
    # sm3_prof_test()
    # sm3_compare_test()
    # sm4_prof_test()
    # sm4_compare_test()
    # zuc_prof_test()
    # zuc_compare_test()
    # sm2_prof_test()
    # sm2_compare_test()
    # test_SM2_func()
    # sm9_prof_test()
    sm9_compare_test()
    # test_SM9_func()
